import { forwardRef, useEffect, useImperativeHandle, useRef, useState } from "react";
import { convertSizeMapToPx, convertToPx, getUuid, toastShort, isEmpty, deepCopy, defaultColmunWidthConfigCollect } from "../../../utils";
import { CellBorderInfo, ColumnWidthConfigMap, DocConfig, DocExtraConfigInfo, ExcelCellData, ExcelScrollInfo, FrozenInfo, SheetApiSettingParams, SheetGridRange } from "../../../utils/types";
import useReSize from "../../../hooks/useResize";

interface Props {
    initExcelConfig: DocExtraConfigInfo
    initCellDataList: ExcelCellData[],
    onCellValueChange: Function,
    onSheetScrollEnd: Function,
    onSheetMouseUp?: Function
    onRangeSelect?: Function
    onCellMousedown?: Function
}

const LuckySheetWapper = (props: Props, ref: any) => {
    useImperativeHandle(ref, () => ({
        handleSetConfig,
        handleSetZoom,
        handleSetCellFormat,
        handleSetRangeFormat,
        handleGetSelection,
        handleSetSelection,
        handleSetExcelFrozen,
        handleSetExcelGridSize,
        handleSetCellValue,
        handleSetRangeValue,
        handleClearCellValue,
        handleClearRangeValue,
        handleScrollToTagetCell,
        handleScrollToTagetPosition,
        handleSetRangeShow,
        forceRefreshWorkBook,
        handleResizeSheet,
        handleSetRangeMerge,
        handleCancelRangeMerge,
        handleTransCellDataListToGridDataList,
        handleSetDataVerification,
        handleDeleteDataVerification,
        handleSetCellBorder,
        handleSetRangeBorder,
        getLuckySheetInstance,
        handleScrollSheet,
        handleSetColumnWidth,
        handleGetSheetData,
    }));

    const {
        initExcelConfig,
        initCellDataList,
        onCellValueChange,
        onSheetScrollEnd,
        onSheetMouseUp,
        onRangeSelect,
        onCellMousedown
    } = props;

    const luckySheetRef = useRef(null);

    const excelContentRef = useRef(null);

    const [excelRootId] = useState('ExcelRootContainer' + getUuid(8));

    const notCheckSheetChange = useRef<boolean>(false);
    const delayCheckSheetChangeTimer = useRef(null);

    const delayZoomTimer = useRef(null);

    useEffect(() => {
        return () => {
            delayZoomTimer.current && clearTimeout(delayZoomTimer.current);
            delayCheckSheetChangeTimer.current && clearTimeout(delayCheckSheetChangeTimer.current);
        }
    }, [])

    const handleSetConfig = (config) => {
        const oldConfig = luckySheetRef.current.getConfig();
        console.log("oldConfig是---->", oldConfig)
        const newConfig = {
            ...oldConfig,
            ...config,
        }
        console.log("newConfig是---->", newConfig)
        luckySheetRef.current.setConfig(newConfig);
    }

    const handleSetZoom = (zoom: number) => {
        luckySheetRef.current.setSheetZoom(zoom, { order: 0 })
    }

    const getLuckySheetInstance = () => {
        return luckySheetRef.current;
    }

    const handleSetRangeFormat = (cellFormatAttr: string, cellFormatValue: string | CellBorderInfo, range) => {
        // console.log("handleSetRangeFormat---->", cellFormatAttr, cellFormatValue, range)
        const { row, column } = range;
        for (let r = row[0]; r <= row[1]; r++) {
            for (let c = column[0]; c <= column[1]; c++) {
                luckySheetRef.current.setCellFormat(r, c, cellFormatAttr, cellFormatValue)
            }
        }
    }

    /**
     * 
     * @param rowIndex 
     * @param colIndex 
     * @param cellFormatAttr 
     * @param cellFormatValue 
     */
    const handleSetCellFormat = (rowIndex: number, colIndex: number, cellFormatAttr: string, cellFormatValue: any) => {
        luckySheetRef.current.setCellFormat(rowIndex, colIndex, cellFormatAttr, cellFormatValue);
    }

    const handleGetSelection = (e) => {
        const range = luckySheetRef.current.getRange();
        return range;
    }

    /**
     * 
     * @param boundStart 
     * @param boundEnd 
     */
    const handleSetSelection = (range) => {
        luckySheetRef.current.setRangeShow(range);
    };

    const handleScrollSheet = (scrollParams: { scrollLeft?: number, scrollTop?: number, targetRow?: number, targetColumn?: number }) => {
        luckySheetRef.current.scroll(scrollParams);
    }

    /**
     * 设置冻结窗格
     * @param frozenInfo
     */
    const handleSetExcelFrozen = (frozenInfo: FrozenInfo) => {
        console.log("frozenInfo--->", frozenInfo)
        switch (frozenInfo.type) {
            case 'row':
                luckySheetRef.current.setHorizontalFrozen(false)
                break;
            case 'column':
                luckySheetRef.current.setVerticalFrozen(false)
                break;
            case 'rangeRow':
                luckySheetRef.current.setHorizontalFrozen(true, { range: frozenInfo.range })
                break;
            case 'rangeColumn':
                luckySheetRef.current.setVerticalFrozen(true, { range: frozenInfo.range })
                break;
            case 'both':
            case 'rangeBoth':
                luckySheetRef.current.setBothFrozen(true, { range: frozenInfo.range })
                break;
            case 'cancel':
                luckySheetRef.current.cancelFrozen()
                break;
            default:
                break;
        }
    }

    const handleSetExcelGridSize = (newDocConfig: DocConfig) => {
        const { docExtraConfigInfo: { rowHeight, rowHeightUnit, columnWidth, columnWidthUnit } } = newDocConfig;
        let rowHeightConfigMap = {};
        let columnWidthConfigMap = {};
        for (let r = 0; r < 700; r++) {
            rowHeightConfigMap[r] = convertToPx(rowHeight, rowHeightUnit);
        }
        for (let c = 0; c < 30; c++) {
            columnWidthConfigMap[c] = convertToPx(columnWidth, columnWidthUnit);
        }
        luckySheetRef.current.setRowHeight(rowHeightConfigMap);
        luckySheetRef.current.setColumnWidth(columnWidthConfigMap);
    }

    const onCellEditBefore = (range) => {
        // console.log("onCellEditBefore---->", range)
    }

    const onCellUpdated = (r: number, c: number, oldCell: ExcelCellData, newCell: ExcelCellData, isRefresh: boolean) => {
        if (notCheckSheetChange.current) {
            return false;
        }
        // console.log("onCellUpdated--->", r, c, oldCell, newCell, isRefresh)
        newCell.r = r;
        newCell.c = c;
        if (c == 12) {
            onCellValueChange && onCellValueChange(newCell);
        } else if (oldCell && newCell && oldCell.m !== newCell.m) {
            onCellValueChange && onCellValueChange(newCell);
        }
    }

    const _onSheetMouseUp = (cell: ExcelCellData, position: { r: number, c: number }) => {
        // console.log('onSheetMouseup---->', cell, position)
        // onSheetMouseUp && onSheetMouseUp(cell, position);
        // if (notCheckSheetChange.current) {
        //     return false;
        // }
        // const {
        //     r,
        //     c
        // } = position;
        // if (isEmpty(cell)) {
        //     cell = {};
        // }
        // cell.r = r;
        // cell.c = c;
        // // if (cell.c == 11) {
        // //     onCellValueChange && onCellValueChange(cell);
        // // }
    }

    const _onCellMousedown = () => {
        onCellMousedown && onCellMousedown();
    }

    const _onRangeSelect = () => {
        onRangeSelect && onRangeSelect();
    }

    const handleSetCellValue = (r: number, c: number, value: number | string) => {
        setCellUpdateInterceptTimer();
        luckySheetRef.current.setCellValue(r, c, value)
    }

    const handleClearCellValue = (r: number, c: number) => {
        setCellUpdateInterceptTimer();
        luckySheetRef.current.clearCell(r, c)
    }

    const onSheetScroll = (e) => {
        onSheetScrollEnd && onSheetScrollEnd(e)
    }

    const handleScrollToTagetCell = (targetCell: { rowIndex: number, clomunIndex: number }) => {
        const {
            rowIndex,
            clomunIndex
        } = targetCell;
        const sheetScrollInfo: ExcelScrollInfo = {};
        if (!isEmpty(rowIndex)) {
            sheetScrollInfo.targetRow = rowIndex;
        }
        if (!isEmpty(clomunIndex)) {
            sheetScrollInfo.targetColumn = clomunIndex;
        }
        luckySheetRef.current.scroll(sheetScrollInfo);
    }

    const handleScrollToTagetPosition = (left: number, right: number) => {

    }

    const handleSetRangeShow = (range: SheetGridRange, settings?: { success?: Function }) => {
        luckySheetRef.current.setRangeShow(range, settings)
    }

    const forceRefreshWorkBook = () => {
        luckySheetRef.current.refresh();
    }

    const handleResizeSheet = (cellGridData: ExcelCellData[][], range: SheetGridRange) => {
        luckySheetRef.current.resize(cellGridData, { range });
    }

    const setCellUpdateInterceptTimer = () => {
        if (delayCheckSheetChangeTimer.current) {
            clearTimeout(delayCheckSheetChangeTimer.current);
        }
        notCheckSheetChange.current = true;
        delayCheckSheetChangeTimer.current = setTimeout(() => {
            notCheckSheetChange.current = false;
        }, 300);
    }
    const handleSetRangeValue = (gridData: ExcelCellData[][], range: SheetGridRange) => {
        setCellUpdateInterceptTimer();
        // console.log("handleSetRangeValue---->", gridData, range)
        luckySheetRef.current.setRangeValue(gridData, { range })
        // gridData.forEach(cellDataGroup => {
        //     cellDataGroup.forEach(cellData => {
        //         handleSetCellValue(cellData.r, cellData.c, cellData.m)
        //     })
        // })
    }

    const handleClearRangeValue = (range: SheetGridRange) => {
        setCellUpdateInterceptTimer();
        // console.log("handleClearRangeValue--->range--->", range)
        luckySheetRef.current.clearRange(
            { range },
            {
                success: () => {
                    console.log("清除内容成功")
                }
            })
    }

    const handleTransCellDataListToGridDataList = (cellDataList: ExcelCellData) => {
        return luckySheetRef.current.transToData(cellDataList);
    }

    const handleSetRangeMerge = (range: SheetGridRange) => {
        // console.log("handleSetRangeMerge--->range--->", range)
        handleSetRangeShow(range, {
            success: () => {
                luckySheetRef.current.setRangeMerge('horizontal', { range })
            }
        });
    }

    const handleCancelRangeMerge = (range: SheetGridRange) => {
        // console.log("handleCancelRangeMerge--->", range)
        luckySheetRef.current.cancelRangeMerge({ range });
    }

    const handleSetDataVerification = (dataVerificationItem, settings: SheetApiSettingParams) => {
        luckySheetRef.current.setDataVerification(dataVerificationItem, settings)
    }

    const handleDeleteDataVerification = (settings: SheetApiSettingParams) => {
        luckySheetRef.current.deleteDataVerification(settings);
    }

    const handleSetCellBorder = (row: number, column: number, borderInfo: CellBorderInfo) => {
        luckySheetRef.current.setCellFormat(row, column, borderInfo, borderInfo)
    }

    const handleSetRangeBorder = (borderInfo: CellBorderInfo, settings: SheetApiSettingParams) => {
        console.log("handleSetRangeBorder--->", borderInfo, settings)
        // luckySheetRef.current.setCellFormat(5, 1, "bd", {borderType: "border-right",style: "13", color: "#ff0000"})
        // luckySheetRef.current.setRangeFormat('bd', borderInfo, {range: ["A10:B12"]});
        // forceRefreshWorkBook();
        // luckySheetRef.current.setRangeFormat("bd", {borderType: "border-right",style: "1", color: "#ff0000"}, {range:["A1:B2"]})
    }

    const handleSetColumnWidth = (columnWidthMap: Record<number, number>) => {
        luckySheetRef.current.setColumnWidth(columnWidthMap);
    }

    const handleGetSheetData = () => {
        return luckySheetRef.current.getSheetData();
    };

    useEffect(() => {
        //@ts-ignore
        const luckySheet = window.luckysheet;
        const excelRowLen = {};
        const excelColumnLen = {};
        const { columnWidthConfigCollect = defaultColmunWidthConfigCollect, rowHeightConfigCollect = {} } = initExcelConfig;
        const { keys, values } = Object;
        const columnWidthConfigCollectValueList = values(columnWidthConfigCollect);
        const rowHeightConfigCollectValueList = values(rowHeightConfigCollect);
        keys(columnWidthConfigCollect).forEach((columnIndex, index) => {
            excelColumnLen[columnIndex] = convertToPx(columnWidthConfigCollectValueList[index].columnWidth, 'lb')
        })
        keys(rowHeightConfigCollect).forEach((rowIndex, index) => {
            excelRowLen[rowIndex] = convertToPx(rowHeightConfigCollectValueList[index].rowHeight, 'lb')
        })
        luckySheet.create({
            container: 'excelRootId',
            lang: 'zh',
            showinfobar: false,  //顶部信息栏
            showsheetbar: false, //底部sheet切换栏
            showstatisticBar: false, //底部计数栏
            showstatisticBarConfig: {
                count: false, // 计数栏
                view: false, // 打印视图
                zoom: false, // 缩放
            },
            showtoolbar: false,
            showConfigWindowResize: false,
            sheetFormulaBar: false,
            enableAddRow: false,
            column: 30,
            row: 700,
            columnHeaderHeight: 30,
            devicePixelRatio: window.devicePixelRatio ? window.devicePixelRatio : 3,
            cellContextMenu: [],
            showFormulaBar: false,
            showToolbar: false,
            defaultFontSize: 12,
            enableAddBackTop: false,
            allowCopy: false,
            data: [{
                id: '1',
                name: "投资估算表",
                defaultRowHeight: convertToPx(initExcelConfig.rowHeight, initExcelConfig.rowHeightUnit),
                defaultColWidth: convertToPx(initExcelConfig.columnWidth, initExcelConfig.columnWidthUnit),
                zoomRatio: initExcelConfig.zoom ? initExcelConfig.zoom : 1,
                //@ts-ignore
                celldata: initCellDataList,
                config: {
                    borderInfo: initExcelConfig.borderInfo ? initExcelConfig.borderInfo : [],
                    merge: initExcelConfig.mergeBoundInfo,
                    rowlen: excelRowLen,
                    columnlen: excelColumnLen,
                    // columnlen: convertSizeMapToPx(initExcelConfig.cutsomColumnWidthMap, initExcelConfig.columnWidthUnit),
                    // rowlen: convertSizeMapToPx(initExcelConfig.cutsomRowHeightMap, initExcelConfig.rowHeightUnit)
                },
                frozen: initExcelConfig.frozenInfo ? initExcelConfig.frozenInfo : null,
                scrollLeft: initExcelConfig.scrollInfo && initExcelConfig.scrollInfo.scrollLeft ? initExcelConfig.scrollInfo.scrollLeft : 0,
                scrollTop: initExcelConfig.scrollInfo && initExcelConfig.scrollInfo.scrollTop ? initExcelConfig.scrollInfo.scrollTop : 0,
                dataVerification: initExcelConfig.dataVerificationMap ? initExcelConfig.dataVerificationMap : null
            }],
            hook: {

                cellEditBefore: onCellEditBefore,
                cellUpdated: onCellUpdated,
                sheetMouseup: _onSheetMouseUp,
                cellMousedown: _onCellMousedown,
                rangeSelect: _onRangeSelect,
                scroll: onSheetScroll,

            }
        })
        luckySheetRef.current = luckySheet;
        if (!luckySheet) {
            toastShort('error', 'Excel渲染异常')
        }
        return () => {
            //@ts-ignore
            window.luckysheet && window.luckysheet.destroy();
        }
    }, [])

    const excelContentSize = useReSize(excelContentRef)

    useEffect(() => {
        if (excelContentSize.width && luckySheetRef.current) {
            if (delayZoomTimer.current) {
                clearTimeout(delayZoomTimer.current);
            }
            delayZoomTimer.current = setTimeout(() => {
                luckySheetRef.current && luckySheetRef.current.resize();
            }, 100);
        }
    }, [excelContentSize])
    
    return (
        <div
            ref={excelContentRef}
            id={'excelRootId'}
            style={{ width: '100%', height: '100%', backgroundColor: '#fff' }}
        >
        </div>
    )
}


export default forwardRef(LuckySheetWapper);